Last updated: 12 Feb 2018 by PTH

This notebook will help us determine which clones from the dBFA2 have adaptive fitness traces across the experiment from the following source environments:

  1. 37C
  2. 21C
  3. 0.2M NaCl
  4. SC pH 7.3
  5. SC pH 3.8

The goal is to identify a set of approx. 96 additional genomes to sequence, with as many from each of the five environments as possible without having to sample clone barcodes from clone plats too deeply to find them.

The strategy will be as follows: 1. Use fitness data (minus drug environments) from dBFA2 to call clones as adapted or not, heuristically based on \(3 * \sigma\) from the neutral class. 2. Use the frequency of these putative adapted clones in the 2N dBFA sub-pool sequencing data as an estimate of prevalence among the clone plate wells. This will help us estimate how deeply we need to barcode PCR and Sanger sequence in order to find the clone.

First, load packages:

library(ggplot2)
Error in library(ggplot2) : there is no package called ‘ggplot2’
system("mv fit_filter00.txt data")
mv: rename fit_filter00.txt to data/fit_filter00.txt: No such file or directory

Now let’s import Milo’s latest dBFA2 counts file so we can extract the neutral barcodes:

system("gdrive download 0BxIjwA18EynHMi1iWHJrc3hDQU0")
Downloading dBFA2_combined.csv -> dBFA2_combined.csv

                                                  
32.8 KB
                                                  
6.7 MB
                                                  
Downloaded 0BxIjwA18EynHMi1iWHJrc3hDQU0 at 6.7 MB/s, total 6.7 MB

Let’s grab the neutral class and store their barcodes

# relevant columns:
  # AncestorPool.YPD.C.1
  # AncestorPool.YPD.C.2
neutral_BCs <- dBFA2[(dBFA2[,'AncestorPool.YPD.C.1']>0) | (dBFA2[,'AncestorPool.YPD.C.2']>0),'Full.BC']

Now we’ll flag the rows in the fitness data that hit these neutrals:

fit[,'neut'] <- 0
fit[fit[,'row_data.Barcode']%in% neutral_BCs,'neut'] <- 1

It looks like Lucas already called these clones as adaptive based on some z-score cutoff from the neutral distribution. What we’ll do is use this information to create a vector of calls across the measured environmetns, then plot the distribution of the neutrals themselves (null distribution).

Let’s check out a quick table of the adapted calls for these neutral sets from a couple environments:

fitb <- fit[fit[,'neut']=='1',names(fit) %in% c('row_data.Barcode', grep('pZvalue', names(fit), value = T))] # grab only neutrals and relevant columns:
fitc <- melt(fitb, measure.vars = grep('pZvalue', names(fit), value = T), id.vars = 'row_data.Barcode')
table(fitc[,'variable'],fitc[,'value'])
                             
                              adaptive non-adaptive
  X02M_NaCl_R1_Zscore_pZvalue        0          335
  X21C_R1_Zscore_pZvalue             1          357
  X37C_R1_Zscore_pZvalue             0          351
  CLM_R1_Zscore_pZvalue              0           19
  FLC_R1_Zscore_pZvalue              0          132
  GlyEtOH_R1_Zscore_pZvalue          1          354
  SC_R1_Zscore_pZvalue               0          351
  YPD_R1_Zscore_pZvalue              0          355
  pH3_8_R1_Zscore_pZvalue            4          351
  pH7_3_R1_Zscore_pZvalue            1          351

Looks like based on the z-score assessment that these calls were already fairly conservative (only \(n=7\) adaptive calls where neutral == TRUE). This is a reasonable false discovery rate and we’ll keep it for these purposes.

Next we’ll grab all of the clones that have ‘adapted’ in their home environment for the five target environments listed above:

        targets[,'t0.freq'][spC.BCs %in% targets[,'BC']] <- targets[,'t0.count'][spC.BCs %in% targets[,'BC']] / t0.sum.C
Error in `[<-.data.frame`(`*tmp*`, , "t0.freq", value = c(0.00108018807980684,  : 
  replacement has 335 rows, data has 111

Now that we have compiled all of the relevant information, we can plot by environment. As an example, let’s plot 0.2M NaCl, which only had one sub-pool (‘D’) sequenced. We will use t0 information where data do not exist

rownames(subdat) <- subdat[,'BC']
# now plot scatter:
g3 <- ggplot(subdat, aes(x = s.home, y = round(t0.freq*384), col = s.home, size = t0.freq*384, group = BC)) + geom_point() + theme_bw() + scale_color_gradientn(colors = viridis(10)) + facet_wrap(~ SP)
ggplotly(g3)
We recommend that you use the dev version of ggplot2 with `ggplotly()`
Install it with: `devtools::install_github('hadley/ggplot2')`
subdat <- dplyr::filter(adapteds, source == '21C') %>% arrange(t0.freq)
subdat[,'BC'] <- factor(subdat[,'BC'], levels = subdat[,'BC'])
rownames(subdat) <- subdat[,'BC']
# now plot scatter:
g3 <- ggplot(subdat, aes(x = s.home, y = round(t0.freq*384), col = s.home, size = t0.freq*384, group = BC)) + geom_point() + theme_bw() + scale_color_gradientn(colors = viridis(10)) + facet_wrap(~ SP)
ggplotly(g3)
We recommend that you use the dev version of ggplot2 with `ggplotly()`
Install it with: `devtools::install_github('hadley/ggplot2')`
subdat <- dplyr::filter(adapteds, source == 'pH3_8') %>% arrange(t0.freq)
subdat[,'BC'] <- factor(subdat[,'BC'], levels = subdat[,'BC'])
rownames(subdat) <- subdat[,'BC']
# now plot scatter:
g3 <- ggplot(subdat, aes(x = s.home, y = round(t0.freq*384), col = s.home, size = t0.freq*384, group = BC)) + geom_point() + theme_bw() + scale_color_gradientn(colors = viridis(10)) + facet_wrap(~ SP)
ggplotly(g3)
We recommend that you use the dev version of ggplot2 with `ggplotly()`
Install it with: `devtools::install_github('hadley/ggplot2')`

These frequencies aren’t correct, since they’re not normalized to the correct denominator. Thus, I’ll need to renormalize based on all lineages in sub-pool before making determination and simulating sampling.

APPROACH 2

The approach above was poorly conceived and was overly complicated and barely functional. The better approach is to simply sample from the Subpool columns and then compute the proportion of unique and adapted barcodes per sampling effort. It doesn’t really matter what the barcodes are or which fitness they have, honestly. I need to draw directly from a vector of column lists that I supply.

Basically, with two plates of Sanger sequencing, we could locate approx. 40 adaptive clones from three total environments. Probably its worth Sanger sequencing the pH7.3 samples since we could potentially boost our changes of WGS new clones if we condition on not having sampled them via Sanger in a large proportion of wells. For the 21C and 02M NaCl, it’s probably worth doing some Sanger sequencing also just to narrow down the sequence space.

This doesn’t look correct since we should capture the total number of clones that are adaptive once we sample fully. Is this what we find?

# this is how many were adaptive in the simulation
res.full %>% group_by(sp) %>% filter(N == max(N)) %>% summarise(max.adapt = max(n.adapt))

Ok the simulation adequately captures the number of adapted lineages in the sub-pool with sub-pool sequences. Now, for all of those sub-pools that were not sequenced, let’s use the \(t_0\) information to estimate frequencies.

These include: 21C.C 02M.D 37C.C

Figure out why I’m not sampling the 37C adaptive clones:

N adaptive in 37C:

fitdat %>% filter(row_data.Home_env %in% grep('37C',row_data.Home_env, value = T)) %>% summarise(tot.adapt = sum(X37C_R1_Zscore_pZvalue  == 'adaptive', na.rm = T))

In this plot, red are the 37C clones while gray are the YPD clones, presumed to all be neutral except maybe for a small number. Clearly the zero is poorly defined in this dataset, since it should be relative to the YPD neutral class. But there is a red shoulder, indicating some sizeable number of non-neutral clones. These are the ones I should be able to sample, but for some reason they’re not showing up in the adaptive column. I’ll set my own threshold here, which is defined as beyond a cutoff, which I will define for each environment below:

Look at adaptive BCs in dBFA2 from 37C with neutrals plotted:

Set up vector of cutoffs and then run the sampling routine to estimate adapteds per sample:

res.list <- list()
res.plots <- list()
for (l in 1:length(subpools)){
  sps <- subpool.sample(dat = dBFA2, fitdat = fit, fitcols = bfa.envs, sp = subpools[l], reps = 100, cutoff = cuts[l])
  res.list[[l]] <- sps$data
  res.plots[[l]] <- sps$plot
}
[1] "Subpool.SC.C:8"
[1] "Subpool.SC.C:16"
[1] "Subpool.SC.C:24"
[1] "Subpool.SC.C:32"
[1] "Subpool.SC.C:40"
[1] "Subpool.SC.C:48"
[1] "Subpool.SC.C:56"
[1] "Subpool.SC.C:64"
[1] "Subpool.SC.C:72"
[1] "Subpool.SC.C:80"
[1] "Subpool.SC.C:88"
[1] "Subpool.SC.C:96"
[1] "Subpool.SC.C:104"
[1] "Subpool.SC.C:112"
[1] "Subpool.SC.C:120"
[1] "Subpool.SC.C:128"
[1] "Subpool.SC.C:136"
[1] "Subpool.SC.C:144"
[1] "Subpool.SC.C:152"
[1] "Subpool.SC.C:160"
[1] "Subpool.SC.C:168"
[1] "Subpool.SC.C:176"
[1] "Subpool.SC.C:184"
[1] "Subpool.SC.C:192"
[1] "Subpool.SC.C:200"
[1] "Subpool.SC.C:208"
[1] "Subpool.SC.C:216"
[1] "Subpool.SC.C:224"
[1] "Subpool.SC.C:232"
[1] "Subpool.SC.C:240"
[1] "Subpool.SC.C:248"
[1] "Subpool.SC.C:256"
[1] "Subpool.SC.C:264"
[1] "Subpool.SC.C:272"
[1] "Subpool.SC.C:280"
[1] "Subpool.SC.C:288"
[1] "Subpool.SC.C:296"
[1] "Subpool.SC.C:304"
[1] "Subpool.SC.C:312"
[1] "Subpool.SC.C:320"
[1] "Subpool.SC.C:328"
[1] "Subpool.SC.C:336"
[1] "Subpool.SC.C:344"
[1] "Subpool.SC.C:352"
[1] "Subpool.SC.C:360"
[1] "Subpool.SC.D:8"
[1] "Subpool.SC.D:16"
[1] "Subpool.SC.D:24"
[1] "Subpool.SC.D:32"
[1] "Subpool.SC.D:40"
[1] "Subpool.SC.D:48"
[1] "Subpool.SC.D:56"
[1] "Subpool.SC.D:64"
[1] "Subpool.SC.D:72"
[1] "Subpool.SC.D:80"
[1] "Subpool.SC.D:88"
[1] "Subpool.SC.D:96"
[1] "Subpool.SC.D:104"
[1] "Subpool.SC.D:112"
[1] "Subpool.SC.D:120"
[1] "Subpool.SC.D:128"
[1] "Subpool.SC.D:136"
[1] "Subpool.SC.D:144"
[1] "Subpool.SC.D:152"
[1] "Subpool.SC.D:160"
[1] "Subpool.SC.D:168"
[1] "Subpool.SC.D:176"
[1] "Subpool.SC.D:184"
[1] "Subpool.SC.D:192"
[1] "Subpool.SC.D:200"
[1] "Subpool.SC.D:208"
[1] "Subpool.SC.D:216"
[1] "Subpool.SC.D:224"
[1] "Subpool.SC.D:232"
[1] "Subpool.SC.D:240"
[1] "Subpool.SC.D:248"
[1] "Subpool.SC.D:256"
[1] "Subpool.SC.D:264"
[1] "Subpool.SC.D:272"
[1] "Subpool.SC.D:280"
[1] "Subpool.SC.D:288"
[1] "Subpool.SC.D:296"
[1] "Subpool.SC.D:304"
[1] "Subpool.SC.D:312"
[1] "Subpool.SC.D:320"
[1] "Subpool.SC.D:328"
[1] "Subpool.SC.D:336"
[1] "Subpool.SC.D:344"
[1] "Subpool.SC.D:352"
[1] "Subpool.SC.D:360"
[1] "Subpool.37C.C:8"
[1] "Subpool.37C.C:16"
[1] "Subpool.37C.C:24"
[1] "Subpool.37C.C:32"
[1] "Subpool.37C.C:40"
[1] "Subpool.37C.C:48"
[1] "Subpool.37C.C:56"
[1] "Subpool.37C.C:64"
[1] "Subpool.37C.C:72"
[1] "Subpool.37C.C:80"
[1] "Subpool.37C.C:88"
[1] "Subpool.37C.C:96"
[1] "Subpool.37C.C:104"
[1] "Subpool.37C.C:112"
[1] "Subpool.37C.C:120"
[1] "Subpool.37C.C:128"
[1] "Subpool.37C.C:136"
[1] "Subpool.37C.C:144"
[1] "Subpool.37C.C:152"
[1] "Subpool.37C.C:160"
[1] "Subpool.37C.C:168"
[1] "Subpool.37C.C:176"
[1] "Subpool.37C.C:184"
[1] "Subpool.37C.C:192"
[1] "Subpool.37C.C:200"
[1] "Subpool.37C.C:208"
[1] "Subpool.37C.C:216"
[1] "Subpool.37C.C:224"
[1] "Subpool.37C.C:232"
[1] "Subpool.37C.C:240"
[1] "Subpool.37C.C:248"
[1] "Subpool.37C.C:256"
[1] "Subpool.37C.C:264"
[1] "Subpool.37C.C:272"
[1] "Subpool.37C.C:280"
[1] "Subpool.37C.C:288"
[1] "Subpool.37C.C:296"
[1] "Subpool.37C.C:304"
[1] "Subpool.37C.C:312"
[1] "Subpool.37C.C:320"
[1] "Subpool.37C.C:328"
[1] "Subpool.37C.C:336"
[1] "Subpool.37C.C:344"
[1] "Subpool.37C.C:352"
[1] "Subpool.37C.C:360"
[1] "Subpool.37C.D:8"
[1] "Subpool.37C.D:16"
[1] "Subpool.37C.D:24"
[1] "Subpool.37C.D:32"
[1] "Subpool.37C.D:40"
[1] "Subpool.37C.D:48"
[1] "Subpool.37C.D:56"
[1] "Subpool.37C.D:64"
[1] "Subpool.37C.D:72"
[1] "Subpool.37C.D:80"
[1] "Subpool.37C.D:88"
[1] "Subpool.37C.D:96"
[1] "Subpool.37C.D:104"
[1] "Subpool.37C.D:112"
[1] "Subpool.37C.D:120"
[1] "Subpool.37C.D:128"
[1] "Subpool.37C.D:136"
[1] "Subpool.37C.D:144"
[1] "Subpool.37C.D:152"
[1] "Subpool.37C.D:160"
[1] "Subpool.37C.D:168"
[1] "Subpool.37C.D:176"
[1] "Subpool.37C.D:184"
[1] "Subpool.37C.D:192"
[1] "Subpool.37C.D:200"
[1] "Subpool.37C.D:208"
[1] "Subpool.37C.D:216"
[1] "Subpool.37C.D:224"
[1] "Subpool.37C.D:232"
[1] "Subpool.37C.D:240"
[1] "Subpool.37C.D:248"
[1] "Subpool.37C.D:256"
[1] "Subpool.37C.D:264"
[1] "Subpool.37C.D:272"
[1] "Subpool.37C.D:280"
[1] "Subpool.37C.D:288"
[1] "Subpool.37C.D:296"
[1] "Subpool.37C.D:304"
[1] "Subpool.37C.D:312"
[1] "Subpool.37C.D:320"
[1] "Subpool.37C.D:328"
[1] "Subpool.37C.D:336"
[1] "Subpool.37C.D:344"
[1] "Subpool.37C.D:352"
[1] "Subpool.37C.D:360"
[1] "Subpool.pH3_8.C:8"
[1] "Subpool.pH3_8.C:16"
[1] "Subpool.pH3_8.C:24"
[1] "Subpool.pH3_8.C:32"
[1] "Subpool.pH3_8.C:40"
[1] "Subpool.pH3_8.C:48"
[1] "Subpool.pH3_8.C:56"
[1] "Subpool.pH3_8.C:64"
[1] "Subpool.pH3_8.C:72"
[1] "Subpool.pH3_8.C:80"
[1] "Subpool.pH3_8.C:88"
[1] "Subpool.pH3_8.C:96"
[1] "Subpool.pH3_8.C:104"
[1] "Subpool.pH3_8.C:112"
[1] "Subpool.pH3_8.C:120"
[1] "Subpool.pH3_8.C:128"
[1] "Subpool.pH3_8.C:136"
[1] "Subpool.pH3_8.C:144"
[1] "Subpool.pH3_8.C:152"
[1] "Subpool.pH3_8.C:160"
[1] "Subpool.pH3_8.C:168"
[1] "Subpool.pH3_8.C:176"
[1] "Subpool.pH3_8.C:184"
[1] "Subpool.pH3_8.C:192"
[1] "Subpool.pH3_8.C:200"
[1] "Subpool.pH3_8.C:208"
[1] "Subpool.pH3_8.C:216"
[1] "Subpool.pH3_8.C:224"
[1] "Subpool.pH3_8.C:232"
[1] "Subpool.pH3_8.C:240"
[1] "Subpool.pH3_8.C:248"
[1] "Subpool.pH3_8.C:256"
[1] "Subpool.pH3_8.C:264"
[1] "Subpool.pH3_8.C:272"
[1] "Subpool.pH3_8.C:280"
[1] "Subpool.pH3_8.C:288"
[1] "Subpool.pH3_8.C:296"
[1] "Subpool.pH3_8.C:304"
[1] "Subpool.pH3_8.C:312"
[1] "Subpool.pH3_8.C:320"
[1] "Subpool.pH3_8.C:328"
[1] "Subpool.pH3_8.C:336"
[1] "Subpool.pH3_8.C:344"
[1] "Subpool.pH3_8.C:352"
[1] "Subpool.pH3_8.C:360"
[1] "Subpool.pH3_8.D:8"
[1] "Subpool.pH3_8.D:16"
[1] "Subpool.pH3_8.D:24"
[1] "Subpool.pH3_8.D:32"
[1] "Subpool.pH3_8.D:40"
[1] "Subpool.pH3_8.D:48"
[1] "Subpool.pH3_8.D:56"
[1] "Subpool.pH3_8.D:64"
[1] "Subpool.pH3_8.D:72"
[1] "Subpool.pH3_8.D:80"
[1] "Subpool.pH3_8.D:88"
[1] "Subpool.pH3_8.D:96"
[1] "Subpool.pH3_8.D:104"
[1] "Subpool.pH3_8.D:112"
[1] "Subpool.pH3_8.D:120"
[1] "Subpool.pH3_8.D:128"
[1] "Subpool.pH3_8.D:136"
[1] "Subpool.pH3_8.D:144"
[1] "Subpool.pH3_8.D:152"
[1] "Subpool.pH3_8.D:160"
[1] "Subpool.pH3_8.D:168"
[1] "Subpool.pH3_8.D:176"
[1] "Subpool.pH3_8.D:184"
[1] "Subpool.pH3_8.D:192"
[1] "Subpool.pH3_8.D:200"
[1] "Subpool.pH3_8.D:208"
[1] "Subpool.pH3_8.D:216"
[1] "Subpool.pH3_8.D:224"
[1] "Subpool.pH3_8.D:232"
[1] "Subpool.pH3_8.D:240"
[1] "Subpool.pH3_8.D:248"
[1] "Subpool.pH3_8.D:256"
[1] "Subpool.pH3_8.D:264"
[1] "Subpool.pH3_8.D:272"
[1] "Subpool.pH3_8.D:280"
[1] "Subpool.pH3_8.D:288"
[1] "Subpool.pH3_8.D:296"
[1] "Subpool.pH3_8.D:304"
[1] "Subpool.pH3_8.D:312"
[1] "Subpool.pH3_8.D:320"
[1] "Subpool.pH3_8.D:328"
[1] "Subpool.pH3_8.D:336"
[1] "Subpool.pH3_8.D:344"
[1] "Subpool.pH3_8.D:352"
[1] "Subpool.pH3_8.D:360"
[1] "Subpool.pH7_3.C:8"
[1] "Subpool.pH7_3.C:16"
[1] "Subpool.pH7_3.C:24"
[1] "Subpool.pH7_3.C:32"
[1] "Subpool.pH7_3.C:40"
[1] "Subpool.pH7_3.C:48"
[1] "Subpool.pH7_3.C:56"
[1] "Subpool.pH7_3.C:64"
[1] "Subpool.pH7_3.C:72"
[1] "Subpool.pH7_3.C:80"
[1] "Subpool.pH7_3.C:88"
[1] "Subpool.pH7_3.C:96"
[1] "Subpool.pH7_3.C:104"
[1] "Subpool.pH7_3.C:112"
[1] "Subpool.pH7_3.C:120"
[1] "Subpool.pH7_3.C:128"
[1] "Subpool.pH7_3.C:136"
[1] "Subpool.pH7_3.C:144"
[1] "Subpool.pH7_3.C:152"
[1] "Subpool.pH7_3.C:160"
[1] "Subpool.pH7_3.C:168"
[1] "Subpool.pH7_3.C:176"
[1] "Subpool.pH7_3.C:184"
[1] "Subpool.pH7_3.C:192"
[1] "Subpool.pH7_3.C:200"
[1] "Subpool.pH7_3.C:208"
[1] "Subpool.pH7_3.C:216"
[1] "Subpool.pH7_3.C:224"
[1] "Subpool.pH7_3.C:232"
[1] "Subpool.pH7_3.C:240"
[1] "Subpool.pH7_3.C:248"
[1] "Subpool.pH7_3.C:256"
[1] "Subpool.pH7_3.C:264"
[1] "Subpool.pH7_3.C:272"
[1] "Subpool.pH7_3.C:280"
[1] "Subpool.pH7_3.C:288"
[1] "Subpool.pH7_3.C:296"
[1] "Subpool.pH7_3.C:304"
[1] "Subpool.pH7_3.C:312"
[1] "Subpool.pH7_3.C:320"
[1] "Subpool.pH7_3.C:328"
[1] "Subpool.pH7_3.C:336"
[1] "Subpool.pH7_3.C:344"
[1] "Subpool.pH7_3.C:352"
[1] "Subpool.pH7_3.C:360"
[1] "Subpool.pH7_3.D:8"
[1] "Subpool.pH7_3.D:16"
[1] "Subpool.pH7_3.D:24"
[1] "Subpool.pH7_3.D:32"
[1] "Subpool.pH7_3.D:40"
[1] "Subpool.pH7_3.D:48"
[1] "Subpool.pH7_3.D:56"
[1] "Subpool.pH7_3.D:64"
[1] "Subpool.pH7_3.D:72"
[1] "Subpool.pH7_3.D:80"
[1] "Subpool.pH7_3.D:88"
[1] "Subpool.pH7_3.D:96"
[1] "Subpool.pH7_3.D:104"
[1] "Subpool.pH7_3.D:112"
[1] "Subpool.pH7_3.D:120"
[1] "Subpool.pH7_3.D:128"
[1] "Subpool.pH7_3.D:136"
[1] "Subpool.pH7_3.D:144"
[1] "Subpool.pH7_3.D:152"
[1] "Subpool.pH7_3.D:160"
[1] "Subpool.pH7_3.D:168"
[1] "Subpool.pH7_3.D:176"
[1] "Subpool.pH7_3.D:184"
[1] "Subpool.pH7_3.D:192"
[1] "Subpool.pH7_3.D:200"
[1] "Subpool.pH7_3.D:208"
[1] "Subpool.pH7_3.D:216"
[1] "Subpool.pH7_3.D:224"
[1] "Subpool.pH7_3.D:232"
[1] "Subpool.pH7_3.D:240"
[1] "Subpool.pH7_3.D:248"
[1] "Subpool.pH7_3.D:256"
[1] "Subpool.pH7_3.D:264"
[1] "Subpool.pH7_3.D:272"
[1] "Subpool.pH7_3.D:280"
[1] "Subpool.pH7_3.D:288"
[1] "Subpool.pH7_3.D:296"
[1] "Subpool.pH7_3.D:304"
[1] "Subpool.pH7_3.D:312"
[1] "Subpool.pH7_3.D:320"
[1] "Subpool.pH7_3.D:328"
[1] "Subpool.pH7_3.D:336"
[1] "Subpool.pH7_3.D:344"
[1] "Subpool.pH7_3.D:352"
[1] "Subpool.pH7_3.D:360"
[1] "Subpool.21C.D:8"
[1] "Subpool.21C.D:16"
[1] "Subpool.21C.D:24"
[1] "Subpool.21C.D:32"
[1] "Subpool.21C.D:40"
[1] "Subpool.21C.D:48"
[1] "Subpool.21C.D:56"
[1] "Subpool.21C.D:64"
[1] "Subpool.21C.D:72"
[1] "Subpool.21C.D:80"
[1] "Subpool.21C.D:88"
[1] "Subpool.21C.D:96"
[1] "Subpool.21C.D:104"
[1] "Subpool.21C.D:112"
[1] "Subpool.21C.D:120"
[1] "Subpool.21C.D:128"
[1] "Subpool.21C.D:136"
[1] "Subpool.21C.D:144"
[1] "Subpool.21C.D:152"
[1] "Subpool.21C.D:160"
[1] "Subpool.21C.D:168"
[1] "Subpool.21C.D:176"
[1] "Subpool.21C.D:184"
[1] "Subpool.21C.D:192"
[1] "Subpool.21C.D:200"
[1] "Subpool.21C.D:208"
[1] "Subpool.21C.D:216"
[1] "Subpool.21C.D:224"
[1] "Subpool.21C.D:232"
[1] "Subpool.21C.D:240"
[1] "Subpool.21C.D:248"
[1] "Subpool.21C.D:256"
[1] "Subpool.21C.D:264"
[1] "Subpool.21C.D:272"
[1] "Subpool.21C.D:280"
[1] "Subpool.21C.D:288"
[1] "Subpool.21C.D:296"
[1] "Subpool.21C.D:304"
[1] "Subpool.21C.D:312"
[1] "Subpool.21C.D:320"
[1] "Subpool.21C.D:328"
[1] "Subpool.21C.D:336"
[1] "Subpool.21C.D:344"
[1] "Subpool.21C.D:352"
[1] "Subpool.21C.D:360"
[1] "Subpool.02M_NaCl.D:8"
[1] "Subpool.02M_NaCl.D:16"
[1] "Subpool.02M_NaCl.D:24"
[1] "Subpool.02M_NaCl.D:32"
[1] "Subpool.02M_NaCl.D:40"
[1] "Subpool.02M_NaCl.D:48"
[1] "Subpool.02M_NaCl.D:56"
[1] "Subpool.02M_NaCl.D:64"
[1] "Subpool.02M_NaCl.D:72"
[1] "Subpool.02M_NaCl.D:80"
[1] "Subpool.02M_NaCl.D:88"
[1] "Subpool.02M_NaCl.D:96"
[1] "Subpool.02M_NaCl.D:104"
[1] "Subpool.02M_NaCl.D:112"
[1] "Subpool.02M_NaCl.D:120"
[1] "Subpool.02M_NaCl.D:128"
[1] "Subpool.02M_NaCl.D:136"
[1] "Subpool.02M_NaCl.D:144"
[1] "Subpool.02M_NaCl.D:152"
[1] "Subpool.02M_NaCl.D:160"
[1] "Subpool.02M_NaCl.D:168"
[1] "Subpool.02M_NaCl.D:176"
[1] "Subpool.02M_NaCl.D:184"
[1] "Subpool.02M_NaCl.D:192"
[1] "Subpool.02M_NaCl.D:200"
[1] "Subpool.02M_NaCl.D:208"
[1] "Subpool.02M_NaCl.D:216"
[1] "Subpool.02M_NaCl.D:224"
[1] "Subpool.02M_NaCl.D:232"
[1] "Subpool.02M_NaCl.D:240"
[1] "Subpool.02M_NaCl.D:248"
[1] "Subpool.02M_NaCl.D:256"
[1] "Subpool.02M_NaCl.D:264"
[1] "Subpool.02M_NaCl.D:272"
[1] "Subpool.02M_NaCl.D:280"
[1] "Subpool.02M_NaCl.D:288"
[1] "Subpool.02M_NaCl.D:296"
[1] "Subpool.02M_NaCl.D:304"
[1] "Subpool.02M_NaCl.D:312"
[1] "Subpool.02M_NaCl.D:320"
[1] "Subpool.02M_NaCl.D:328"
[1] "Subpool.02M_NaCl.D:336"
[1] "Subpool.02M_NaCl.D:344"
[1] "Subpool.02M_NaCl.D:352"
[1] "Subpool.02M_NaCl.D:360"
res.full <- do.call(rbind, res.list)
# summarise the data:
res.full2 <- group_by(res.full, sp, N) %>% summarise(mean.n.adapt = round(sum(n.adapt)/length(n.adapt)), lower = round(quantile(n.adapt, probs = 0.025)), upper = round(quantile(n.adapt, probs = 0.975)))
# plot the data:
g1 <- ggplot(res.full2, aes(x = N, y = mean.n.adapt, ymin = lower, ymax = upper, group = sp)) + geom_point() + geom_linerange() + geom_line() + facet_wrap(~ sp, scales = 'free') + theme_bw() + ggtitle('cutoffs are 2*sigma > mean(neut)') + scale_x_continuous(limits = c(0,100))
pdf(file = here('adaptive_sampling_2N.pdf'), width = 7, height = 5)
print(g1)
dev.off()
null device 
          1 
print(g1)

Now do the same plot but for the whole data range, up to \(n=384\):

g2 <- ggplot(res.full2, aes(x = N, y = mean.n.adapt, ymin = lower, ymax = upper, group = sp)) + geom_point() + geom_linerange() + geom_line() + facet_wrap(~ sp, scales = 'free') + theme_bw() + ggtitle('cutoffs are 2*sigma > mean(neut)')# + scale_x_continuous(limits = c(0,100))
pdf(file = here('adaptive_sampling_2N_384.pdf'), width = 7, height = 5)
print(g2)
dev.off()
null device 
          1 
print(g2)

This looks far more reasonable than the first iteration of the sampler. Now we can actually get a chance to check each environment and replicate on its own.

I’ll also plot the frequency distribution of clone BCs from each sub-pool so we can get a sense for how skewed these distributions are. This will help inform whether we would even be able to do compressed sensing on these clones.

Save data

save.image(here("021418.RData"))
LS0tCnRpdGxlOiAiSWRlbnRpZnlpbmcgYWRkaXRpb25hbCBhZGFwdGVkIDJOIGNsb25lcyB0byBzZXF1ZW5jZSIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKKkxhc3QgdXBkYXRlZDogMTIgRmViIDIwMTggYnkgUFRIKgoKVGhpcyBub3RlYm9vayB3aWxsIGhlbHAgdXMgZGV0ZXJtaW5lIHdoaWNoIGNsb25lcyBmcm9tIHRoZSBkQkZBMiBoYXZlIGFkYXB0aXZlIGZpdG5lc3MgdHJhY2VzIGFjcm9zcyB0aGUgZXhwZXJpbWVudCBmcm9tIHRoZSBmb2xsb3dpbmcgc291cmNlIGVudmlyb25tZW50czoKCjEuIDM3QyAgCjIuIDIxQwozLiAwLjJNIE5hQ2wKNC4gU0MgcEggNy4zCjUuIFNDIHBIIDMuOAoKVGhlIGdvYWwgaXMgdG8gaWRlbnRpZnkgYSBzZXQgb2YgYXBwcm94LiA5NiBhZGRpdGlvbmFsIGdlbm9tZXMgdG8gc2VxdWVuY2UsIHdpdGggYXMgbWFueSBmcm9tIGVhY2ggb2YgdGhlIGZpdmUgZW52aXJvbm1lbnRzIGFzIHBvc3NpYmxlIHdpdGhvdXQgaGF2aW5nIHRvIHNhbXBsZSBjbG9uZSBiYXJjb2RlcyBmcm9tIGNsb25lIHBsYXRzIHRvbyBkZWVwbHkgdG8gZmluZCB0aGVtLgoKVGhlIHN0cmF0ZWd5IHdpbGwgYmUgYXMgZm9sbG93czoKMS4gVXNlIGZpdG5lc3MgZGF0YSAobWludXMgZHJ1ZyBlbnZpcm9ubWVudHMpIGZyb20gZEJGQTIgdG8gY2FsbCBjbG9uZXMgYXMgYWRhcHRlZCBvciBub3QsIGhldXJpc3RpY2FsbHkgYmFzZWQgb24gJDMgKiBcc2lnbWEkIGZyb20gdGhlIG5ldXRyYWwgY2xhc3MuCjIuIFVzZSB0aGUgZnJlcXVlbmN5IG9mIHRoZXNlIHB1dGF0aXZlIGFkYXB0ZWQgY2xvbmVzIGluIHRoZSAyTiBkQkZBIHN1Yi1wb29sIHNlcXVlbmNpbmcgZGF0YSBhcyBhbiBlc3RpbWF0ZSBvZiBwcmV2YWxlbmNlIGFtb25nIHRoZSBjbG9uZSBwbGF0ZSB3ZWxscy4gVGhpcyB3aWxsIGhlbHAgdXMgZXN0aW1hdGUgaG93IGRlZXBseSB3ZSBuZWVkIHRvIGJhcmNvZGUgUENSIGFuZCBTYW5nZXIgc2VxdWVuY2UgaW4gb3JkZXIgdG8gZmluZCB0aGUgY2xvbmUuCgpGaXJzdCwgbG9hZCBwYWNrYWdlczoKYGBge3J9CmxpYnJhcnkoaGVyZSkKbGlicmFyeShkcGx5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHJlc2hhcGUyKQpsaWJyYXJ5KHBsb3RseSkKYGBgCgpgYGB7cn0KIyBsb2FkIGRhdGE6CiNzeXN0ZW0oImdkcml2ZSBkb3dubG9hZCAxeC1tLVEzYXlfaDVuS19xanZ2b0xBOFVKUmtJM19oWDIiKSAjIGZpdDA0CnN5c3RlbSgiZ2RyaXZlIGRvd25sb2FkIDEzRHpPZ2NBUGhlbnpfSkh4WC03WVNkakowSmkwd29vTSIpICMgZml0ICpubyBmaWx0ZXIpCiNzeXN0ZW0oIm12IGZpdF9maWx0ZXIwNC50eHQgZGF0YSIpCnN5c3RlbSgibXYgZml0X2FsbC50eHQgZGF0YSIpCiMgZG93bmxvYWRzIEx1Y2FzJyBmaXRuZXNzIGVzdGltYXRlIGJhc2VkIG9uIGhhcnNoIGVycm9yIGZpbHRlcgojIGZpbGVuYW1lOiBmaXRfZmlsdGVyMDQudHh0CmZpdCA8LSByZWFkLnRhYmxlKGhlcmUoImRhdGEiLCJmaXRfYWxsLnR4dCIpLFQsIlx0IikKYGBgCgpOb3cgbGV0J3MgaW1wb3J0IE1pbG8ncyBsYXRlc3QgZEJGQTIgY291bnRzIGZpbGUgc28gd2UgY2FuIGV4dHJhY3QgdGhlIG5ldXRyYWwgYmFyY29kZXM6CmBgYHtyfQojIHVzaW5nIGRCRkEyIGNvdW50IGZpbGUgZnJvbSBPY3QgNyAyMDE3CnN5c3RlbSgiZ2RyaXZlIGRvd25sb2FkIDBCeElqd0ExOEV5bkhNaTFpV0hKcmMzaERRVTAiKQpzeXN0ZW0oIm12IGRCRkEyX2NvbWJpbmVkLmNzdiBkYXRhIikKZEJGQTIgPC0gcmVhZC5jc3YoaGVyZSgiZGF0YSIsImRCRkEyX2NvbWJpbmVkLmNzdiIpLFQpCmBgYAoKTGV0J3MgZ3JhYiB0aGUgbmV1dHJhbCBjbGFzcyBhbmQgc3RvcmUgdGhlaXIgYmFyY29kZXMKYGBge3J9CiMgcmVsZXZhbnQgY29sdW1uczoKICAjIEFuY2VzdG9yUG9vbC5ZUEQuQy4xCiAgIyBBbmNlc3RvclBvb2wuWVBELkMuMgpuZXV0cmFsX0JDcyA8LSBkQkZBMlsoZEJGQTJbLCdBbmNlc3RvclBvb2wuWVBELkMuMSddPjApIHwgKGRCRkEyWywnQW5jZXN0b3JQb29sLllQRC5DLjInXT4wKSwnRnVsbC5CQyddCmBgYAoKTm93IHdlJ2xsIGZsYWcgdGhlIHJvd3MgaW4gdGhlIGZpdG5lc3MgZGF0YSB0aGF0IGhpdCB0aGVzZSBuZXV0cmFsczoKYGBge3J9CmZpdFssJ25ldXQnXSA8LSAwCmZpdFtmaXRbLCdyb3dfZGF0YS5CYXJjb2RlJ10laW4lIG5ldXRyYWxfQkNzLCduZXV0J10gPC0gMQpgYGAKCkl0IGxvb2tzIGxpa2UgTHVjYXMgYWxyZWFkeSBjYWxsZWQgdGhlc2UgY2xvbmVzIGFzIGFkYXB0aXZlIGJhc2VkIG9uIHNvbWUgei1zY29yZSBjdXRvZmYgZnJvbSB0aGUgbmV1dHJhbCBkaXN0cmlidXRpb24uIFdoYXQgd2UnbGwgZG8gaXMgdXNlIHRoaXMgaW5mb3JtYXRpb24gdG8gY3JlYXRlIGEgdmVjdG9yIG9mIGNhbGxzIGFjcm9zcyB0aGUgbWVhc3VyZWQgZW52aXJvbm1ldG5zLCB0aGVuIHBsb3QgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgbmV1dHJhbHMgdGhlbXNlbHZlcyAobnVsbCBkaXN0cmlidXRpb24pLgoKTGV0J3MgY2hlY2sgb3V0IGEgcXVpY2sgdGFibGUgb2YgdGhlIGFkYXB0ZWQgY2FsbHMgZm9yIHRoZXNlIG5ldXRyYWwgc2V0cyBmcm9tIGEgY291cGxlIGVudmlyb25tZW50czoKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMgZ3JhYiByZWxldmFudCBjb2x1bW5zLCBtZWx0LCBhbmQgY29tcHV0ZSB0YWJsZToKZml0YiA8LSBmaXRbZml0WywnbmV1dCddPT0nMScsbmFtZXMoZml0KSAlaW4lIGMoJ3Jvd19kYXRhLkJhcmNvZGUnLCBncmVwKCdwWnZhbHVlJywgbmFtZXMoZml0KSwgdmFsdWUgPSBUKSldICMgZ3JhYiBvbmx5IG5ldXRyYWxzIGFuZCByZWxldmFudCBjb2x1bW5zOgpmaXRjIDwtIG1lbHQoZml0YiwgbWVhc3VyZS52YXJzID0gZ3JlcCgncFp2YWx1ZScsIG5hbWVzKGZpdCksIHZhbHVlID0gVCksIGlkLnZhcnMgPSAncm93X2RhdGEuQmFyY29kZScpCnRhYmxlKGZpdGNbLCd2YXJpYWJsZSddLGZpdGNbLCd2YWx1ZSddKQpgYGAKCkxvb2tzIGxpa2UgYmFzZWQgb24gdGhlIHotc2NvcmUgYXNzZXNzbWVudCB0aGF0IHRoZXNlIGNhbGxzIHdlcmUgYWxyZWFkeSBmYWlybHkgY29uc2VydmF0aXZlIChvbmx5ICRuPTckIGFkYXB0aXZlIGNhbGxzIHdoZXJlIG5ldXRyYWwgPT0gVFJVRSkuIFRoaXMgaXMgYSByZWFzb25hYmxlIGZhbHNlIGRpc2NvdmVyeSByYXRlIGFuZCB3ZSdsbCBrZWVwIGl0IGZvciB0aGVzZSBwdXJwb3Nlcy4gCgpOZXh0IHdlJ2xsIGdyYWIgYWxsIG9mIHRoZSBjbG9uZXMgdGhhdCBoYXZlICdhZGFwdGVkJyBpbiB0aGVpciBob21lIGVudmlyb25tZW50IGZvciB0aGUgZml2ZSB0YXJnZXQgZW52aXJvbm1lbnRzIGxpc3RlZCBhYm92ZToKYGBge3J9CiMgcm91dGluZToKICAjIGxvb3AgdGhyb3VnaCBlYWNoIHNvdXJjZSBlbnZpcm9ubWVudAogICAgIyBncmFiIGFkYXB0ZWQgQkNzIHdoZXJlIHBadmFsdWUgPT0gJ2FkYXB0aXZlJyBmb3IgdGhlIGZvY2FsIGhvbWUgZW52aXJvbm1lbnQKICAgICAgIyBuZWVkIHRvIGRlZmluZSBob21lIGVudmlyb25tZW50IHdoZXJlIGdyZXAgb2YgZW52IG9jY3VycyBhbW9uZyB0aGUgY29sdW1ucyB3aXRoIHBadmFsdWU6CmVudnMgPSBjKCcwMk0nLCcyMUMnLCczN0MnLCdwSDNfOCcsJ3BIN18zJywnU0MnLCdZUEQnKQpiY3MuYWRhcHQuYXQuaG9tZSA8LSBmdW5jdGlvbihkYXQsIGZyZXFkYXQsIGVudnMsIGZyZXEuc3RyID0gJ1N1YnBvb2wnLCB0MCA9ICdkQkZBMi5QcmUuUjAuVGltZTAnLCBiYy5maWVsZCA9ICdyb3dfZGF0YS5CYXJjb2RlJywgYWRhcHRpdmUuY2FsbCA9ICdhZGFwdGl2ZScsIGhvbWUuY2FsbCA9ICdyb3dfZGF0YS5Ib21lX2VudicsIGFkYXB0LmNvbC52YWwgPSAncFp2YWx1ZScsIGZpdC5lcnIuY29sID0gJ19lcnInLCBmaXQuY29sID0gJ1IxJyl7CiAgYzEgPC0gZ3JlcChhZGFwdC5jb2wudmFsLCBuYW1lcyhkYXQpLCB2YWx1ZSA9IFQpICMgaW5pdGlhbGl6ZSB2ZWN0b3Igb2YgYWRhcHRlZC9ub24tYWRhcHRlZCBjb2x1bW5zCiAgQkNzX2xpc3QgPC0gbGlzdCgpCiAgZm9yIChlIGluIDE6bGVuZ3RoKGVudnMpKXsKICAgIGMyIDwtIGdyZXAocGFzdGUwKGVudnNbMV0pLCBjMSwgdmFsdWUgPSBUKSAjIGZpbmQgcmVsZXZhbnQgYWRhcHRlZCB2ZWN0b3IgZm9yIGZvY2FsIGVudmlyb25tZW50CiAgICBmaXQgPC0gZ3JlcChmaXQuY29sLCBuYW1lcyhkYXQpLCB2YWx1ZSA9IFQpICU+JSBncmVwKCdaJywuLCB2YWx1ZSA9IFQsIGludmVydCA9IFQpICU+JSBncmVwKCdfZXJyJywuLHZhbHVlID0gVCwgaW52ZXJ0ID0gVCkgJT4lIGdyZXAoZW52c1tlXSwuLCB2YWx1ZSA9IFQpCiAgICBlcnIgPC0gZ3JlcChmaXQuY29sLCBuYW1lcyhkYXQpLCB2YWx1ZSA9IFQpICU+JSBncmVwKCdaJywuLCB2YWx1ZSA9IFQsIGludmVydCA9IFQpICU+JSBncmVwKCdfZXJyJywuLHZhbHVlID0gVCwgaW52ZXJ0ID0gRikgJT4lIGdyZXAoZW52c1tlXSwuLCB2YWx1ZSA9IFQpCiAgICByMSA8LSBncmVwKGVudnNbZV0sZGF0WyxwYXN0ZTAoaG9tZS5jYWxsKV0pCiAgICAjcHJpbnQobGVuZ3RoKHIxKSkKICAgIHRhcmdldHMgPC0gZGF0YS5mcmFtZShCQyA9IGRhdFtyMSxiYy5maWVsZF1bZGF0W3IxLGMyXT09YWRhcHRpdmUuY2FsbF0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgcy5ob21lID0gZGF0W3IxLGZpdF1bZGF0W3IxLGMyXT09YWRhcHRpdmUuY2FsbF0vOCwKICAgICAgICAgICAgICAgICAgICAgICAgICBzLmVyci5ob21lID0gZGF0W3IxLGVycl1bZGF0W3IxLGMyXT09YWRhcHRpdmUuY2FsbF0vOCwKICAgICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2UgPSBlbnZzW2VdKQogICAgdGFyZ2V0cyA8LSB0YXJnZXRzW2NvbXBsZXRlLmNhc2VzKHRhcmdldHMpLF0KICAgIAogICAgIyBhc3NpZ24gcmVsYXRpdmUgZnJlcXVlbmN5IGZyb20gdDAgcG9vbAogICAgdDAuc3VtIDwtIHN1bShmcmVxZGF0Wyx0MF0pCiAgICAKICAgICMgYWRkIGZyZXF1ZW5jeSBpbmZvcm1hdGlvbiB0byB0YXJnZXRzIGJhc2VkIG9uIG1hdGNoIG9mIEJDOgogICAgIyBkZWZpbmUgcm93cyBmcm9tIGZyZXFkYXQgdG8gd3JpdGUgdG8gdGFyZ2V0czoKICAgIHRoZXJvd3MgPC0gbWF0Y2godGFyZ2V0c1ssJ0JDJ10sIGZyZXFkYXRbLCdGdWxsLkJDJ10pCiAgICB0YXJnZXRzWywndDAuY291bnQnXSA8LSBmcmVxZGF0W3RoZXJvd3MsdDBdCiAgICBmcmVxLmNvbHMgPC0gZ3JlcChmcmVxLnN0ciwgbmFtZXMoZnJlcWRhdCksIHZhbHVlID0gVCkgJT4lIGdyZXAoZW52c1tlXSwuLHZhbHVlID0gVCkgIyBzaG91bGQgYmUgbGVuZ3RoIDIgaWYgd2UgaGF2ZSBib3RoIHN1Yi1wb29sIHJlcHMKICAgIAogICAgIyBjYWxjdWxhdGUgc3VtcyBvZiB0MCBDIGFuZCBEIHBvb2xzLCBhcyB3ZWxsIGFzIHN1YnBvb2wuQyBhbmQgc3VicG9vbC5EIHN1bXM6CiAgICAjIGZpbmQgcm93cyBmb3IgQkNzIHdpdGggY291bnRzIGluIFNQLkMgYW5kIFNQLkQsIGFjY291bnRpbmYgZm9yIHRoZSBwb3RlbnRpYWwgYWJzZW5jZSBvZiBzdWJwb29sOgogICAgCiAgICBpZihsZW5ndGgoZnJlcS5jb2xzKSA9PSAxKXsKICAgICAgCiAgICAgICMgZGVmaW5lIHN1Yi1wb29sIGlkZW50aXR5OgogICAgICBsYXN0LmNoYXIgPC0gbGFzdCh1bmxpc3Qoc3Ryc3BsaXQoZnJlcS5jb2xzLCBzcGxpdCA9ICcnKSkpCiAgICAgIGlmIChsYXN0LmNoYXIgJWluJSBjKCdSMScsJ0MnKSkgewogICAgICAgIGNvbG5hbWUgPC0gcGFzdGUwKCdTdWJwb29sLicsbGFzdC5jaGFyKQogICAgICAgIHRhcmdldHNbLGNvbG5hbWVdIDwtIGZyZXFkYXRbdGhlcm93cyxmcmVxLmNvbHNdCiAgICAgICAgCiAgICAgICAgIyBjYWxjdWxhdGUgZnJlcXVlbmN5IGluZm9ybWF0aW9uIGJhc2VkIG9uIHRvdGFsIHN1YnBvb2wgcmVhZHM6CiAgICAgICAgY29sbmFtZTIgPC0gcGFzdGUwKCdTdWJwb29sLicsbGFzdC5jaGFyLCcuZnJlcScpCiAgICAgICAgdGFyZ2V0c1ssY29sbmFtZTJdIDwtIGZyZXFkYXRbdGhlcm93cyxmcmVxLmNvbHNdIC8gc3VtKGZyZXFkYXRbLGZyZXEuY29sc10pCiAgICAgICAgCiAgICAgICAgIyBjYWxjdWxhdGUgc3VtIHRvdGFsIG9mIHJlYWRzIGZvciBhbGwgYmFyY29kZXMgZnJvbSB0aGUgcmVsZXZhbnQgc3VwLXBvb2wgaW4gdGhlIHQwIGxpYnJhcnkuCiAgICAgICAgIyB0aGlzIHdpbGwgYmUgdXNlIHRvIHJlLW5vcm1hbGl6ZSBmcmVxdWVuY2llcyBvZiBhZGFwdGVkIGxpbmVhZ2VzIGRvd25zdHJlYW0KICAgICAgICAjIEkgbmVlZCB0byBmaW5kIGFsbCByb3dzIG1hdGNoaW5nIHNvdXJjZSBlbnZpcm9ubWVudAogICAgICAgICMgYW5kIHN1YnRyYWN0IG91dCB0aG9zZSB3aXRoIGNvdW50cyBpbiBmcmVxLmNvbAogICAgICAgIHNwQy5CQ3MgPC0gZnJlcWRhdFtmcmVxZGF0WyxmcmVxLmNvbHNdPjAsJ0Z1bGwuQkMnXQogICAgICAgIGFsbC5CQ3MgPC0gZnJlcWRhdFssJ0Z1bGwuQkMnXVtncmVwKGVudnNbZV0sZnJlcWRhdFssJ0Vudmlyb25tZW50J10pXQogICAgICAgIHNwRC5CQ3MgPC0gYWxsLkJDc1shYWxsLkJDcyAlaW4lIHNwQy5CQ3NdCiAgICAgICAgCiAgICAgICAgdDAuc3VtLkMgPC0gc3VtKGZyZXFkYXRbLGZyZXEuY29sXVtmcmVxZGF0WywnRnVsbC5CQyddICVpbiUgc3BDLkJDc10pCiAgICAgICAgdDAuc3VtLkQgPC0gc3VtKGZyZXFkYXRbLGZyZXEuY29sXVtmcmVxZGF0WywnRnVsbC5CQyddICVpbiUgc3BELkJDc10pCiAgICAgICAgCiAgICAgICAgIyBhZGQgJ0QnIGNvbHVtbiBhcyAnTkEnCiAgICAgICAgdGFyZ2V0c1sscGFzdGUwKCdTdWJwb29sLkQnKV0gPC0gTkEKICAgICAgICB0YXJnZXRzWyxwYXN0ZTAoJ1N1YnBvb2wuRC5mcmVxJyldIDwtIE5BCiAgICAgICAgdGFyZ2V0c1ssJ3QwLmZyZXEnXSA8LSBOQQogICAgICAgIHRhcmdldHNbLCd0MC5mcmVxJ11bc3BDLkJDcyAlaW4lIHRhcmdldHNbLCdCQyddXSA8LSB0YXJnZXRzWywndDAuY291bnQnXVtzcEMuQkNzICVpbiUgdGFyZ2V0c1ssJ0JDJ11dIC8gdDAuc3VtLkMKICAgICAgICB0YXJnZXRzWywndDAuZnJlcSddW3NwRC5CQ3MgJWluJSB0YXJnZXRzWywnQkMnXV0gPC0gdGFyZ2V0c1ssJ3QwLmNvdW50J11bc3BELkJDcyAlaW4lIHRhcmdldHNbLCdCQyddXSAvIHQwLnN1bS5ECiAgICAgICAgdGFyZ2V0c1ssJ3QwLmZyZXEnXVt0YXJnZXRzWywndDAuZnJlcSddPjFdIDwtIE5BCiAgICAgICAgCiAgICAgICAgIyMgVEhJUyBJU04nVCBXT1JLSU5HIFlFVCEgSSBuZWVkIHRvIGZpZ3VyZSBvdXQgaG93IHRvIGdldCB0MCBpbmZvcm1hdGlvbiByZWxldmFudCBmb3IgdGhlIG5vbi1leGlzdGVudCBzdWItcG9vbC4KICAgICAgICAKICAgICAgICAKICAgICAgfSBlbHNlIHsKICAgICAgICB0YXJnZXRzWyxwYXN0ZTAoJ1N1YnBvb2wuQycpXSA8LSBOQQogICAgICAgIHRhcmdldHNbLHBhc3RlMCgnU3VicG9vbC5DLmZyZXEnKV0gPC0gTkEKICAgICAgICBjb2xuYW1lIDwtIHBhc3RlMCgnU3VicG9vbC4nLGxhc3QuY2hhcikKICAgICAgICB0YXJnZXRzWyxjb2xuYW1lXSA8LSBmcmVxZGF0W3RoZXJvd3MsZnJlcS5jb2xzXQogICAgICAgIAogICAgICAgIGNvbG5hbWUyIDwtIHBhc3RlMCgnU3VicG9vbC4nLGxhc3QuY2hhciwnLmZyZXEnKQogICAgICAgIHRhcmdldHNbLGNvbG5hbWUyXSA8LSBmcmVxZGF0W3RoZXJvd3MsZnJlcS5jb2xzXSAvIHN1bShmcmVxZGF0WyxmcmVxLmNvbHNdKQogICAgICAgIAogICAgICB9CiAgICB9IGVsc2UgaWYgKGxlbmd0aChmcmVxLmNvbHMpID09IDIpewogICAgICAjIGRvIGZvciBlYWNoOgogICAgICBjb2xuYW1lIDwtIGMocGFzdGUwKCdTdWJwb29sLicsbGFzdCh1bmxpc3Qoc3Ryc3BsaXQoZnJlcS5jb2xzWzFdLCBzcGxpdCA9ICcnKSkpKSwKICAgICAgICAgICAgICAgICAgIHBhc3RlMCgnU3VicG9vbC4nLGxhc3QodW5saXN0KHN0cnNwbGl0KGZyZXEuY29sc1syXSwgc3BsaXQgPSAnJykpKSkpCiAgICAgIHRhcmdldHNbLGNvbG5hbWVbMV1dIDwtIGZyZXFkYXRbdGhlcm93cyxmcmVxLmNvbHNbMV1dIC8gc3VtKGZyZXFkYXRbdGhlcm93cyxmcmVxLmNvbHNbMV1dKQogICAgICB0YXJnZXRzWyxjb2xuYW1lWzJdXSA8LSBmcmVxZGF0W3RoZXJvd3MsZnJlcS5jb2xzWzJdXSAvIHN1bShmcmVxZGF0W3RoZXJvd3MsZnJlcS5jb2xzWzJdXSkKICAgIH0KICAgICMgZnJlcWRhdDIgPC0gZnJlcWRhdFssbmFtZXMoZnJlcWRhdCkgJWluJSBjKCdGdWxsLkJDJyxmcmVxLmNvbCldCiAgICAjIGZyZXFzdW0gPC0gc3VtKGZyZXFkYXQyWyxmcmVxLmNvbF0pCiAgICAjIGZyZXFkYXQyWyxmcmVxLmNvbF1bZnJlcWRhdDJbLCdGdWxsLkJDJ10gJWluJSB0YXJnZXRzWywnQkMnXV0KICAgIAogICAgIyBhZGQgc3VicG9vbCBpbmZvcm1hdGlvbiB0byBTUCBjb2x1bW46CiAgICB0YXJnZXRzWywnU1AnXSA8LSAnQycKICAgIHRhcmdldHNbLCdTUCddW3RhcmdldHNbLCdTdWJwb29sLkQnXT4wXSA8LSAnRCcKICAgIAogICAgIyB0YXJnZXRzWywndDAuZnJlcSddIDwtIHRhcmdldHNbLCd0MC5jb3VudCddIC8gc3VtKHRhcmdldHNbLCd0MC5jb3VudCddKSAjIHJlbm9ybWFsaXplZCBvdmVyYWxsCiAgICAjIHJlLW5vcm1hbGl6ZSB0MCBjb3VudHMgd2l0aGluIHJlc3BlY3RpdmUgc3ViLXBvb2xzOgogICAgdDAuQyA8LSBzdW0odGFyZ2V0c1ssJ3QwLmNvdW50J11bdGFyZ2V0c1ssJ1NQJ109PSdDJ10pCiAgICB0MC5EIDwtIHN1bSh0YXJnZXRzWywndDAuY291bnQnXVt0YXJnZXRzWywnU1AnXT09J0QnXSkKICAgIHRhcmdldHNbLCd0MC5mcmVxJ10gPC0gMAogICAgdGFyZ2V0c1t0YXJnZXRzWywnU1AnXSAlaW4lIGMoJ0MnKSwndDAuZnJlcSddIDwtIHRhcmdldHNbLCd0MC5jb3VudCddW3RhcmdldHNbLCdTUCddPT0nQyddIC8gdDAuQwogICAgdGFyZ2V0c1t0YXJnZXRzWywnU1AnXSAlaW4lIGMoJ0QnKSwndDAuZnJlcSddIDwtIHRhcmdldHNbLCd0MC5jb3VudCddW3RhcmdldHNbLCdTUCddPT0nRCddIC8gdDAuRAogICAgCiAgICBCQ3NfbGlzdFtbZV1dIDwtIHRhcmdldHMKICAgIH0KICBuYW1lcyhCQ3NfbGlzdCkgPC0gZW52cwogIHJldHVybihCQ3NfbGlzdCkKfQoKYWRhcHRlZF9CQ3MgPC0gYmNzLmFkYXB0LmF0LmhvbWUoZGF0ID0gZml0MDQsIGZyZXFkYXQgPSBkQkZBMiwgZW52cyA9IGMoJzAyTScsJzIxQycsJzM3QycsJ3BIM184JywncEg3XzMnLCdTQycsJ1lQRCcpKQphZGFwdGVkcyA8LSBkby5jYWxsKHJiaW5kLGFkYXB0ZWRfQkNzKQpgYGAKCk5vdyB0aGF0IHdlIGhhdmUgY29tcGlsZWQgYWxsIG9mIHRoZSByZWxldmFudCBpbmZvcm1hdGlvbiwgd2UgY2FuIHBsb3QgYnkgZW52aXJvbm1lbnQuIEFzIGFuIGV4YW1wbGUsIGxldCdzIHBsb3QgMC4yTSBOYUNsLCB3aGljaCBvbmx5IGhhZCBvbmUgc3ViLXBvb2wgKCdEJykgc2VxdWVuY2VkLiBXZSB3aWxsIHVzZSB0MCBpbmZvcm1hdGlvbiB3aGVyZSBkYXRhIGRvIG5vdCBleGlzdApgYGB7ciwgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9OCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KIyB0cnkgbW9jay11cCBwbG90IHVzaW5nIHQwOgpzdWJkYXQgPC0gZHBseXI6OmZpbHRlcihhZGFwdGVkcywgc291cmNlID09ICcwMk0nKSAlPiUgYXJyYW5nZShzLmhvbWUpCnN1YmRhdFssJ0JDJ10gPC0gZmFjdG9yKHN1YmRhdFssJ0JDJ10sIGxldmVscyA9IHN1YmRhdFssJ0JDJ10pCgojIHBsb3QgYnkgZml0bmVzcwpnMSA8LSBnZ3Bsb3Qoc3ViZGF0LCBhZXMoeCA9IEJDLCB5ID0gcy5ob21lLCB5bWluID0gcy5ob21lIC0gcy5lcnIuaG9tZSwgeW1heCA9IHMuaG9tZSArIHMuZXJyLmhvbWUsIGNvbCA9IGxvZyh0MC5mcmVxLDEwKSkpICsgZ2VvbV9wb2ludCgpICsgZ2VvbV9saW5lcmFuZ2UoKSArIHRoZW1lX2J3KCkKCiMgcGxvdCBieSBmcmVxdWVuY3kKc3ViZGF0IDwtIGRwbHlyOjpmaWx0ZXIoYWRhcHRlZHMsIHNvdXJjZSA9PSAnMDJNJykgJT4lIGFycmFuZ2UodDAuZnJlcSkKc3ViZGF0WywnQkMnXSA8LSBmYWN0b3Ioc3ViZGF0WywnQkMnXSwgbGV2ZWxzID0gc3ViZGF0WywnQkMnXSkKZzIgPC0gZ2dwbG90KHN1YmRhdCwgYWVzKHggPSBCQywgeSA9IHQwLmZyZXEqMzg0LCBjb2wgPSBzLmhvbWUpKSsgZ2VvbV9wb2ludCgpICsgdGhlbWVfYncoKSArIHNjYWxlX2NvbG9yX2dyYWRpZW50bihjb2xvcnMgPSB2aXJpZGlzKDEwKSkKZzIKCnJvd25hbWVzKHN1YmRhdCkgPC0gc3ViZGF0WywnQkMnXQojIG5vdyBwbG90IHNjYXR0ZXI6CmczIDwtIGdncGxvdChzdWJkYXQsIGFlcyh4ID0gcy5ob21lLCB5ID0gcm91bmQodDAuZnJlcSozODQpLCBjb2wgPSBzLmhvbWUsIHNpemUgPSB0MC5mcmVxKjM4NCwgZ3JvdXAgPSBCQykpICsgZ2VvbV9wb2ludCgpICsgdGhlbWVfYncoKSArIHNjYWxlX2NvbG9yX2dyYWRpZW50bihjb2xvcnMgPSB2aXJpZGlzKDEwKSkgKyBmYWNldF93cmFwKH4gU1ApCmdncGxvdGx5KGczKQpgYGAKCmBgYHtyfQpzdWJkYXQgPC0gZHBseXI6OmZpbHRlcihhZGFwdGVkcywgc291cmNlID09ICczN0MnKSAlPiUgYXJyYW5nZSh0MC5mcmVxKQpzdWJkYXRbLCdCQyddIDwtIGZhY3RvcihzdWJkYXRbLCdCQyddLCBsZXZlbHMgPSBzdWJkYXRbLCdCQyddKQoKcm93bmFtZXMoc3ViZGF0KSA8LSBzdWJkYXRbLCdCQyddCiMgbm93IHBsb3Qgc2NhdHRlcjoKZzMgPC0gZ2dwbG90KHN1YmRhdCwgYWVzKHggPSBzLmhvbWUsIHkgPSByb3VuZCh0MC5mcmVxKjM4NCksIGNvbCA9IHMuaG9tZSwgc2l6ZSA9IHQwLmZyZXEqMzg0LCBncm91cCA9IEJDKSkgKyBnZW9tX3BvaW50KCkgKyB0aGVtZV9idygpICsgc2NhbGVfY29sb3JfZ3JhZGllbnRuKGNvbG9ycyA9IHZpcmlkaXMoMTApKSArIGZhY2V0X3dyYXAofiBTUCkKZ2dwbG90bHkoZzMpCmBgYAoKYGBge3J9CnN1YmRhdCA8LSBkcGx5cjo6ZmlsdGVyKGFkYXB0ZWRzLCBzb3VyY2UgPT0gJzIxQycpICU+JSBhcnJhbmdlKHQwLmZyZXEpCnN1YmRhdFssJ0JDJ10gPC0gZmFjdG9yKHN1YmRhdFssJ0JDJ10sIGxldmVscyA9IHN1YmRhdFssJ0JDJ10pCgpyb3duYW1lcyhzdWJkYXQpIDwtIHN1YmRhdFssJ0JDJ10KIyBub3cgcGxvdCBzY2F0dGVyOgpnMyA8LSBnZ3Bsb3Qoc3ViZGF0LCBhZXMoeCA9IHMuaG9tZSwgeSA9IHJvdW5kKHQwLmZyZXEqMzg0KSwgY29sID0gcy5ob21lLCBzaXplID0gdDAuZnJlcSozODQsIGdyb3VwID0gQkMpKSArIGdlb21fcG9pbnQoKSArIHRoZW1lX2J3KCkgKyBzY2FsZV9jb2xvcl9ncmFkaWVudG4oY29sb3JzID0gdmlyaWRpcygxMCkpICsgZmFjZXRfd3JhcCh+IFNQKQpnZ3Bsb3RseShnMykKYGBgCgpgYGB7cn0Kc3ViZGF0IDwtIGRwbHlyOjpmaWx0ZXIoYWRhcHRlZHMsIHNvdXJjZSA9PSAncEgzXzgnKSAlPiUgYXJyYW5nZSh0MC5mcmVxKQpzdWJkYXRbLCdCQyddIDwtIGZhY3RvcihzdWJkYXRbLCdCQyddLCBsZXZlbHMgPSBzdWJkYXRbLCdCQyddKQoKcm93bmFtZXMoc3ViZGF0KSA8LSBzdWJkYXRbLCdCQyddCiMgbm93IHBsb3Qgc2NhdHRlcjoKZzMgPC0gZ2dwbG90KHN1YmRhdCwgYWVzKHggPSBzLmhvbWUsIHkgPSByb3VuZCh0MC5mcmVxKjM4NCksIGNvbCA9IHMuaG9tZSwgc2l6ZSA9IHQwLmZyZXEqMzg0LCBncm91cCA9IEJDKSkgKyBnZW9tX3BvaW50KCkgKyB0aGVtZV9idygpICsgc2NhbGVfY29sb3JfZ3JhZGllbnRuKGNvbG9ycyA9IHZpcmlkaXMoMTApKSArIGZhY2V0X3dyYXAofiBTUCkKZ2dwbG90bHkoZzMpCmBgYAoKVGhlc2UgZnJlcXVlbmNpZXMgYXJlbid0IGNvcnJlY3QsIHNpbmNlIHRoZXkncmUgbm90IG5vcm1hbGl6ZWQgdG8gdGhlIGNvcnJlY3QgZGVub21pbmF0b3IuIFRodXMsIEknbGwgbmVlZCB0byByZW5vcm1hbGl6ZSBiYXNlZCBvbiBhbGwgbGluZWFnZXMgaW4gc3ViLXBvb2wgYmVmb3JlIG1ha2luZyBkZXRlcm1pbmF0aW9uIGFuZCBzaW11bGF0aW5nIHNhbXBsaW5nLgoKIyMgQVBQUk9BQ0ggMgoKVGhlIGFwcHJvYWNoIGFib3ZlIHdhcyBwb29ybHkgY29uY2VpdmVkIGFuZCB3YXMgb3Zlcmx5IGNvbXBsaWNhdGVkIGFuZCBiYXJlbHkgZnVuY3Rpb25hbC4gVGhlIGJldHRlciBhcHByb2FjaCBpcyB0byBzaW1wbHkgc2FtcGxlIGZyb20gdGhlIFN1YnBvb2wgY29sdW1ucyBhbmQgdGhlbiBjb21wdXRlIHRoZSBwcm9wb3J0aW9uIG9mIHVuaXF1ZSBhbmQgYWRhcHRlZCBiYXJjb2RlcyBwZXIgc2FtcGxpbmcgZWZmb3J0LiBJdCBkb2Vzbid0IHJlYWxseSBtYXR0ZXIgd2hhdCB0aGUgYmFyY29kZXMgYXJlIG9yIHdoaWNoIGZpdG5lc3MgdGhleSBoYXZlLCBob25lc3RseS4gSSBuZWVkIHRvIGRyYXcgZGlyZWN0bHkgZnJvbSBhIHZlY3RvciBvZiBjb2x1bW4gbGlzdHMgdGhhdCBJIHN1cHBseS4gCgpgYGB7cn0KIyBkZWZpbmUgU3VicG9vbHMgdG8gc2FtcGxlIGZyb206CnN1YnBvb2xzIDwtIGMoZ3JlcCgiU3VicG9vbCIsIG5hbWVzKGRCRkEyKSwgdmFsdWUgPSBUKSAlPiUgZ3JlcCgiNDhIciIsLixpbnZlcnQgPSBULCB2YWx1ZSA9IFQpICU+JSBncmVwKCIwLjhNIiwuLGludmVydCA9IFQsIHZhbHVlID0gVCkpCnN1YnBvb2xzIDwtIHN1YnBvb2xzW2MoMzoxMCwxNiwxNyldCgojIGRlZmluZSBmdW5jdGlvbiB0aGF0IHRha2VzIGVhY2ggc3VicG9vbCBjb2x1bW4gYXMgaW5wdXQgYW5kIGRvZXMgdGhlIGZvbGxvd2luZzoKICAjIHNhbXBsZXMgdG8gZ2l2ZW4gZGVwdGgKICAgICMgY2FsY3VsYXRlcyBudW1iZXIgb2YgYWRhcHRlZCBhbmQgdW5pcXVlIGJhcmNvZGVzIHNlZW4KICAgICAgIyByZXBlYXRzIDEwMCB0aW1lcwogICAgICAgICMgcHJvZHVjZXMgY291cG9uIGNvbGxlY3RvciBjdXJ2ZSBmb3IgZWFjaCBzYW1wbGluZyBkZXB0aCAodXAgdG8gYWxsIGNsb25lcywgbiA9IDM4NCBwZXIgc3ViLXBvb2wpCgojIHNwIGlzIHNpbmdsZSBjaGFyYWN0ZXIgcmVwcmVzZW50aW5nIHRoZSBjb2x1bW4gb2YgZGF0IHRvIGJlIHNhbXBsZWQKIyBuZWVkIHRvIGNvbnN0cnVjdCB0aGUgc2FtcGxpbmcgdmVjdG9yIGFjY29yZGluZyB0byBmcmVxdWVuY2llcyBvZiBlYWNoIGJhcmNvZGU6CnN1YnBvb2wuc2FtcGxlIDwtIGZ1bmN0aW9uKGRhdCwgZml0ZGF0LCBzcCwgTiwgcmVwcyA9IDMwLCBmaXRjb2xzLCBjdXRvZmYgPSAwLjAxNSl7CiAgIyBpbml0aWFsaXplIHJlc3VsdHMgZGF0YS5mcmFtZQogIHJlcy5kYXQgPC0gZGF0YS5mcmFtZShzcCA9IE5BLCBOID0gTkEsIHJlcCA9IE5BLCBuLmFkYXB0ID0gTkEpCiAgcmVzLmRhdCA8LSByZXMuZGF0Wy0xLF0KICAKICAjIGRldGVybWluZSBlbnZpcm9ubWVudCBvZiB0aGUgc3A6CiAgZW52IDwtIHVubGlzdChzdHJzcGxpdChzcCwnXFwuJykpWzJdCiAgIyB0aGVjb2wgPC0gZ3JlcChlbnYsZ3JlcCgncFp2YWx1ZScsIG5hbWVzKGZpdGRhdCksIHZhbHVlID0gVCksIHZhbHVlID0gVCkKICB0aGVjb2wgPC0gZ3JlcChlbnYsZml0Y29scywgdmFsdWUgPSBUKSAjIGRlZmluZSBhcyBmaXRuZXNzIGNvbHVtbiBpdHNlbGYKICBkYXQyIDwtIGRhdFtkYXRbLHNwXT4wLF0gIyB0YWtlIG9ubHkgc2FtcGxlZCBndXlzIHB1dGF0aXZlbHkgaW4gdGFyZ2V0IHN1Yi1wb29sCiAgCiAgIyBtYWtlIHZlY3RvciBmcm9tIHdoaWNoIHRvIHNhbXBsZToKICAjIGRhdDJbLCdiYy5mcmVxJ10gPC0gZGF0Mlssc3BdIC8gc3VtKGRhdDJbLHNwXSkqMzg0CiAgZGF0MlssJ2JjLmZyZXEnXSA8LSBkYXQyWyxzcF0gLyBzdW0oZGF0Mlssc3BdKSAjIGp1c3QgY2FsY3VsYXRlIGVzdGltYXRlZCBmcmVxdWVuY3kKICAjQkMudmVjIDwtIHJlcChkYXQyWywnRnVsbC5CQyddLCBkYXQyWywnYmMuZnJlcSddLCBlYWNoID0gVCkKICAKICAjIGRldGVybWluZyBzYW1wbGluZyBkZXB0aCBzZXF1ZW5jZSAobiA9IDguLi5tYXgoTikpCiAgTiA8LSBjKHNlcSg4LGxlbmd0aChCQy52ZWMpLDgpKQogIAogICMgc2FtcGxpbmcgcm91dGluZwogIGZvciAobiBpbiAxOmxlbmd0aChOKSl7CiAgICBmb3IgKGkgaW4gMTpyZXBzKXsKICAgICAgIyBzYW1wbGUgQkNzIGZyb20gdGFyZ2V0IGNvbHVtbgogICAgICBCQy5zYW1wIDwtIHVuaXF1ZShzYW1wbGUoZGF0MlssJ0Z1bGwuQkMnXSwgc2l6ZSA9IE5bbl0sIHByb2IgPSBkYXQyWywnYmMuZnJlcSddLCByZXBsYWNlPVRSVUUpKQogICAgICAKICAgICAgIyBjb3VudCBob3cgbWFueSBhZGFwdGVkICAKICAgICAgI24uYWRhcHQgPC0gc3VtKGZpdGRhdFssdGhlY29sXVtmaXRkYXRbLCdyb3dfZGF0YS5CYXJjb2RlJ10gJWluJSBwYXN0ZTAoQkMuc2FtcCldID09ICdhZGFwdGl2ZScsIG5hLnJtID0gVFJVRSkKICAgICAgbi5hZGFwdCA8LSBzdW0oZml0ZGF0Wyx0aGVjb2xdW2ZpdGRhdFssJ3Jvd19kYXRhLkJhcmNvZGUnXSAlaW4lIEJDLnNhbXBdID4gY3V0b2ZmKjgsIG5hLnJtID0gVCkKICAgICAgCiAgICAgICMgYWRkIHRvIHJlc3VsdHMgZmlsZQogICAgICByZXMuZGF0IDwtIHJiaW5kKHJlcy5kYXQsIGRhdGEuZnJhbWUoc3AgPSBzcCwgTiA9IE5bbl0sIHJlcCA9IGksIG4uYWRhcHQgPSBuLmFkYXB0KSkKICAgICAgI3ByaW50KGkpCiAgICB9CiAgICBwcmludChwYXN0ZTAoc3AsJzonLE5bbl0pKQogIH0KcDEgPC0gZ2dwbG90KGRhdDIsIGFlcyh4ID0gYmMuZnJlcSkpICsgZ2VvbV9oaXN0b2dyYW0oYmlucyA9IDYwKSArIHRoZW1lX2J3KCkgKyBnZ3RpdGxlKHBhc3RlMChzcCkpICsgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gYygxLzM4NCwyLzM4NCwzLzM4NCw0LzM4NCw1LzM4NCwxMC8zODQpLCBjb2wgPSAiZ3JheTQwIikKcmV0dXJuKGxpc3QoZGF0YSA9IHJlcy5kYXQsCiAgICAgICAgICAgIHBsb3QgPSBwMSkpCn0KYGBgCgpCYXNpY2FsbHksIHdpdGggdHdvIHBsYXRlcyBvZiBTYW5nZXIgc2VxdWVuY2luZywgd2UgY291bGQgbG9jYXRlIGFwcHJveC4gNDAgYWRhcHRpdmUgY2xvbmVzIGZyb20gdGhyZWUgdG90YWwgZW52aXJvbm1lbnRzLiBQcm9iYWJseSBpdHMgd29ydGggU2FuZ2VyIHNlcXVlbmNpbmcgdGhlIHBINy4zIHNhbXBsZXMgc2luY2Ugd2UgY291bGQgcG90ZW50aWFsbHkgYm9vc3Qgb3VyIGNoYW5nZXMgb2YgV0dTIG5ldyBjbG9uZXMgaWYgd2UgY29uZGl0aW9uIG9uIG5vdCBoYXZpbmcgc2FtcGxlZCB0aGVtIHZpYSBTYW5nZXIgaW4gYSBsYXJnZSBwcm9wb3J0aW9uIG9mIHdlbGxzLiBGb3IgdGhlIDIxQyBhbmQgMDJNIE5hQ2wsIGl0J3MgcHJvYmFibHkgd29ydGggZG9pbmcgc29tZSBTYW5nZXIgc2VxdWVuY2luZyBhbHNvIGp1c3QgdG8gbmFycm93IGRvd24gdGhlIHNlcXVlbmNlIHNwYWNlLgoKVGhpcyBkb2Vzbid0IGxvb2sgY29ycmVjdCBzaW5jZSB3ZSBzaG91bGQgY2FwdHVyZSB0aGUgdG90YWwgbnVtYmVyIG9mIGNsb25lcyB0aGF0IGFyZSBhZGFwdGl2ZSBvbmNlIHdlIHNhbXBsZSBmdWxseS4gSXMgdGhpcyB3aGF0IHdlIGZpbmQ/CgpgYGB7cn0KIyB0aGlzIGlzIGhvdyBtYW55IHdlcmUgYWRhcHRpdmUgaW4gdGhlIHNpbXVsYXRpb24KcmVzLmZ1bGwgJT4lIGdyb3VwX2J5KHNwKSAlPiUgZmlsdGVyKE4gPT0gbWF4KE4pKSAlPiUgc3VtbWFyaXNlKG1heC5hZGFwdCA9IG1heChuLmFkYXB0KSkKYGBgCgpgYGB7cn0KIyBjb21wYXJlIHRvIHRoZSBudW1iZXIgYWRhcHRpdmUgaW4gdGhlIHNhbXBsZSBzZXQ6CmFkYXB0ZWRzICU+JSBncm91cF9ieShzb3VyY2UsIFNQKSAlPiUgc3VtbWFyaXNlKHRvdC5hZGFwdGVkcyA9IGxlbmd0aChCQykpCmBgYAoKT2sgdGhlIHNpbXVsYXRpb24gYWRlcXVhdGVseSBjYXB0dXJlcyB0aGUgbnVtYmVyIG9mIGFkYXB0ZWQgbGluZWFnZXMgaW4gdGhlIHN1Yi1wb29sIHdpdGggc3ViLXBvb2wgc2VxdWVuY2VzLiBOb3csIGZvciBhbGwgb2YgdGhvc2Ugc3ViLXBvb2xzIHRoYXQgd2VyZSBub3Qgc2VxdWVuY2VkLCBsZXQncyB1c2UgdGhlICR0XzAkIGluZm9ybWF0aW9uIHRvIGVzdGltYXRlIGZyZXF1ZW5jaWVzLgoKVGhlc2UgaW5jbHVkZToKMjFDLkMKMDJNLkQKMzdDLkMKCkZpZ3VyZSBvdXQgd2h5IEknbSBub3Qgc2FtcGxpbmcgdGhlIDM3QyBhZGFwdGl2ZSBjbG9uZXM6CmBgYHtyfQphZGFwdGVkcyAlPiUgZ3JvdXBfYnkoc291cmNlLCBTUCkgJT4lIGZpbHRlcihzb3VyY2UgJWluJSBncmVwKCIzN0MiLHNvdXJjZSx2YWx1ZSA9VCkpCmBgYApOIGFkYXB0aXZlIGluIDM3QzoKYGBge3J9CmZpdGRhdCAlPiUgZmlsdGVyKHJvd19kYXRhLkhvbWVfZW52ICVpbiUgZ3JlcCgnMzdDJyxyb3dfZGF0YS5Ib21lX2VudiwgdmFsdWUgPSBUKSkgJT4lIHN1bW1hcmlzZSh0b3QuYWRhcHQgPSBzdW0oWDM3Q19SMV9ac2NvcmVfcFp2YWx1ZSAgPT0gJ2FkYXB0aXZlJywgbmEucm0gPSBUKSkKYGBgCgoKSW4gdGhpcyBwbG90LCByZWQgYXJlIHRoZSAzN0MgY2xvbmVzIHdoaWxlIGdyYXkgYXJlIHRoZSBZUEQgY2xvbmVzLCBwcmVzdW1lZCB0byBhbGwgYmUgbmV1dHJhbCBleGNlcHQgbWF5YmUgZm9yIGEgc21hbGwgbnVtYmVyLiBDbGVhcmx5IHRoZSB6ZXJvIGlzIHBvb3JseSBkZWZpbmVkIGluIHRoaXMgZGF0YXNldCwgc2luY2UgaXQgc2hvdWxkIGJlIHJlbGF0aXZlIHRvIHRoZSBZUEQgbmV1dHJhbCBjbGFzcy4gQnV0IHRoZXJlIGlzIGEgcmVkIHNob3VsZGVyLCBpbmRpY2F0aW5nIHNvbWUgc2l6ZWFibGUgbnVtYmVyIG9mIG5vbi1uZXV0cmFsIGNsb25lcy4gVGhlc2UgYXJlIHRoZSBvbmVzIEkgc2hvdWxkIGJlIGFibGUgdG8gc2FtcGxlLCBidXQgZm9yIHNvbWUgcmVhc29uIHRoZXkncmUgbm90IHNob3dpbmcgdXAgaW4gdGhlIGFkYXB0aXZlIGNvbHVtbi4gSSdsbCBzZXQgbXkgb3duIHRocmVzaG9sZCBoZXJlLCB3aGljaCBpcyBkZWZpbmVkIGFzIGJleW9uZCBhIGN1dG9mZiwgd2hpY2ggSSB3aWxsIGRlZmluZSBmb3IgZWFjaCBlbnZpcm9ubWVudCBiZWxvdzoKCmBgYHtyfQojIHNldHRpbmcgY3V0b2ZmcyBmcm9tIFlQRCBuZXV0cmFsIGNsYXNzCiMgZGVmaW5lIG5ldXRyYWwgYmFyY29kZXM6CiMgZmluZCBhbGwgQkNzIGluIEFuY2VzdG9yUG9vbC5ZUEQuQy4xIGFuZCBBbmNlc3RvclBvb2wuWVBELkMuMgpuZXV0cmFscyA8LSBkQkZBMlssJ0Z1bGwuQkMnXVsoZEJGQTJbLCdBbmNlc3RvclBvb2wuWVBELkMuMSddID4gMCl8KGRCRkEyWywnQW5jZXN0b3JQb29sLllQRC5DLjInXSA+IDApXQoKIyBwdWxsIG91dCBmaXRuZXNzIGRhdGEgZm9yIGFsbCBuZXV0cmFsczoKZml0ZGF0ICU+JSBmaWx0ZXIocm93X2RhdGEuQmFyY29kZSAlaW4lIG5ldXRyYWxzKSAtPiBkYXROZXV0CgoKIyBkZWZpbmUgY3V0b2ZmczoKYmZhLmVudnMgPC0gbmFtZXMoZGF0TmV1dClbYygzOjUsODoxMildCgojIGNhcHR1cmUgb25seSBzdWJzZXQgb2YgZGF0TmV1dCB3aXRoIHJlbGV2YW50IGZpdG5lc3MgY29sdW1uczoKZGF0TmV1dDIgPC0gZGF0TmV1dFssbmFtZXMoZGF0TmV1dCkgJWluJSBjKCdyb3dfZGF0YS5CYXJjb2RlJyxiZmEuZW52cyldCmRhdE5ldXQgPC0gZGF0TmV1dDJbY29tcGxldGUuY2FzZXMoZGF0TmV1dDIpLF0KY3V0b2ZmcyA8LSBkYXRhLmZyYW1lKGJmYSA9IE5BLCBuLm11ID0gTkEsIGN1dCA9IE5BKQpjdXRvZmZzIDwtIGN1dG9mZnNbLWMoMSksXQpmb3IgKGIgaW4gMTpsZW5ndGgoYmZhLmVudnMpKXsKICBjdXRvZmZzIDwtIHJiaW5kKGN1dG9mZnMsCiAgICAgICAgICAgICAgICAgICBkYXRhLmZyYW1lKGJmYSA9IGJmYS5lbnZzW2JdLCBuLm11ICA9IG1lYW4oZGF0TmV1dFssYmZhLmVudnNbYl1dLzgpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXQgPSAyKnNkKGRhdE5ldXRbLGJmYS5lbnZzW2JdXS84KSkKICAgICAgICAgICAgICAgICAgICkKfQpgYGAKCgpMb29rIGF0IGFkYXB0aXZlIEJDcyBpbiBkQkZBMiBmcm9tIDM3QyB3aXRoIG5ldXRyYWxzIHBsb3R0ZWQ6CmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpmaXRkYXQgJT4lIGZpbHRlcihyb3dfZGF0YS5Ib21lX2VudiAlaW4lIGdyZXAoJzM3Qycscm93X2RhdGEuSG9tZV9lbnYsIHZhbHVlID0gVCkpIC0+IGRhdDM3CgpwMzdjMSA8LSBnZ3Bsb3QoKSArIGdlb21fZGVuc2l0eShkYXRhID0gZGF0TmV1dCwgYWVzKHggPSBYMzdDX1IxLzgpLCBjb2xvciA9ICJncmF5NDAiKSArIAogIGdlb21fZGVuc2l0eShkYXRhID0gZGF0MzcsIGFlcyh4ID0gWDM3Q19SMS84KSwgY29sb3IgPSAicmVkIikgKyB0aGVtZV9idygpICsgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gY3V0b2Zmc1szLCduLm11J10sIGNvbCA9ICJibGFjayIpICsgCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gYyhjdXRvZmZzWzMsJ24ubXUnXSArICgyKmN1dG9mZnNbMywnbi5zaWcnXSksIGN1dG9mZnNbMywnbi5tdSddIC0gKDIqY3V0b2Zmc1szLCduLnNpZyddKSksIGNvbCA9ICJncmF5NDAiLCBsdHkgPSAiZG90dGVkIikgKwogIHhsYWIoImZpdG5lc3MgKHMpIikKcHJpbnQocDM3YzEpCmBgYAoKU2V0IHVwIHZlY3RvciBvZiBjdXRvZmZzIGFuZCB0aGVuIHJ1biB0aGUgc2FtcGxpbmcgcm91dGluZSB0byBlc3RpbWF0ZSBhZGFwdGVkcyBwZXIgc2FtcGxlOgpgYGB7ciwgZmlnLmhlaWdodD01LCBmaWcud2lkdGg9NywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KY3V0cyA8LSBjdXRvZmZzW2MoNSw1LDMsMyw3LDcsOCw4LDIsMSksJ2N1dCddCgojIGl0ZXJhdGUgdGhyb3VnaCBzdWJwb29scyBhbmQgZ2VuZXJhdGUgc2FtcGxlczoKcmVzLmxpc3QgPC0gbGlzdCgpCnJlcy5wbG90cyA8LSBsaXN0KCkKZm9yIChsIGluIDE6bGVuZ3RoKHN1YnBvb2xzKSl7CiAgc3BzIDwtIHN1YnBvb2wuc2FtcGxlKGRhdCA9IGRCRkEyLCBmaXRkYXQgPSBmaXQsIGZpdGNvbHMgPSBiZmEuZW52cywgc3AgPSBzdWJwb29sc1tsXSwgcmVwcyA9IDEwMCwgY3V0b2ZmID0gY3V0c1tsXSkKICByZXMubGlzdFtbbF1dIDwtIHNwcyRkYXRhCiAgcmVzLnBsb3RzW1tsXV0gPC0gc3BzJHBsb3QKfQoKcmVzLmZ1bGwgPC0gZG8uY2FsbChyYmluZCwgcmVzLmxpc3QpCgojIGV4cG9ydCB0aGlzIHNpbXVsYXRpb24gcmVzdWx0OgpzYXZlUkRTKHJlcy5mdWxsLCBmaWxlID0gaGVyZSgicmVzLmZ1bGwucmRzIikpCnNhdmVSRFMoYWRhcHRlZHMsIGZpbGUgPSBoZXJlKCJhZGFwdGVkcy5yZHMiKSkKCiMgc3VtbWFyaXNlIHRoZSBkYXRhOgpyZXMuZnVsbDIgPC0gZ3JvdXBfYnkocmVzLmZ1bGwsIHNwLCBOKSAlPiUgc3VtbWFyaXNlKG1lYW4ubi5hZGFwdCA9IHJvdW5kKHN1bShuLmFkYXB0KS9sZW5ndGgobi5hZGFwdCkpLCBsb3dlciA9IHJvdW5kKHF1YW50aWxlKG4uYWRhcHQsIHByb2JzID0gMC4wMjUpKSwgdXBwZXIgPSByb3VuZChxdWFudGlsZShuLmFkYXB0LCBwcm9icyA9IDAuOTc1KSkpCgojIHBsb3QgdGhlIGRhdGE6CmcxIDwtIGdncGxvdChyZXMuZnVsbDIsIGFlcyh4ID0gTiwgeSA9IG1lYW4ubi5hZGFwdCwgeW1pbiA9IGxvd2VyLCB5bWF4ID0gdXBwZXIsIGdyb3VwID0gc3ApKSArIGdlb21fcG9pbnQoKSArIGdlb21fbGluZXJhbmdlKCkgKyBnZW9tX2xpbmUoKSArIGZhY2V0X3dyYXAofiBzcCwgc2NhbGVzID0gJ2ZyZWUnKSArIHRoZW1lX2J3KCkgKyBnZ3RpdGxlKCdjdXRvZmZzIGFyZSAyKnNpZ21hID4gbWVhbihuZXV0KScpICsgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwxMDApKQoKcGRmKGZpbGUgPSBoZXJlKCdhZGFwdGl2ZV9zYW1wbGluZ18yTi5wZGYnKSwgd2lkdGggPSA3LCBoZWlnaHQgPSA1KQpwcmludChnMSkKZGV2Lm9mZigpCnByaW50KGcxKQpgYGAKCk5vdyBkbyB0aGUgc2FtZSBwbG90IGJ1dCBmb3IgdGhlIHdob2xlIGRhdGEgcmFuZ2UsIHVwIHRvICRuPTM4NCQ6CmBgYHtyLCBmaWcuaGVpZ2h0PTUsIGZpZy53aWR0aD03LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpnMiA8LSBnZ3Bsb3QocmVzLmZ1bGwyLCBhZXMoeCA9IE4sIHkgPSBtZWFuLm4uYWRhcHQsIHltaW4gPSBsb3dlciwgeW1heCA9IHVwcGVyLCBncm91cCA9IHNwKSkgKyBnZW9tX3BvaW50KCkgKyBnZW9tX2xpbmVyYW5nZSgpICsgZ2VvbV9saW5lKCkgKyBmYWNldF93cmFwKH4gc3AsIHNjYWxlcyA9ICdmcmVlJykgKyB0aGVtZV9idygpICsgZ2d0aXRsZSgnY3V0b2ZmcyBhcmUgMipzaWdtYSA+IG1lYW4obmV1dCknKSMgKyBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLDEwMCkpCgpwZGYoZmlsZSA9IGhlcmUoJ2FkYXB0aXZlX3NhbXBsaW5nXzJOXzM4NC5wZGYnKSwgd2lkdGggPSA3LCBoZWlnaHQgPSA1KQpwcmludChnMikKZGV2Lm9mZigpCnByaW50KGcyKQpgYGAKClRoaXMgbG9va3MgZmFyIG1vcmUgcmVhc29uYWJsZSB0aGFuIHRoZSBmaXJzdCBpdGVyYXRpb24gb2YgdGhlIHNhbXBsZXIuIE5vdyB3ZSBjYW4gYWN0dWFsbHkgZ2V0IGEgY2hhbmNlIHRvIGNoZWNrIGVhY2ggZW52aXJvbm1lbnQgYW5kIHJlcGxpY2F0ZSBvbiBpdHMgb3duLgoKSSdsbCBhbHNvIHBsb3QgdGhlIGZyZXF1ZW5jeSBkaXN0cmlidXRpb24gb2YgY2xvbmUgQkNzIGZyb20gZWFjaCBzdWItcG9vbCBzbyB3ZSBjYW4gZ2V0IGEgc2Vuc2UgZm9yIGhvdyBza2V3ZWQgdGhlc2UgZGlzdHJpYnV0aW9ucyBhcmUuIFRoaXMgd2lsbCBoZWxwIGluZm9ybSB3aGV0aGVyIHdlIHdvdWxkIGV2ZW4gYmUgYWJsZSB0byBkbyBjb21wcmVzc2VkIHNlbnNpbmcgb24gdGhlc2UgY2xvbmVzLgoKIyMgU2F2ZSBkYXRhCmBgYHtyfQpzYXZlLmltYWdlKGhlcmUoIjAyMTQxOC5SRGF0YSIpKQpgYGAKCg==